package com.wsl.HealthChallenge.controllers;

import java.net.URLEncoder;
import java.util.Calendar;
import java.util.Date;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.wsl.HealthChallenge.models.ContestEntry;
import com.wsl.HealthChallenge.models.ContestType;
import com.wsl.HealthChallenge.models.UserEntry;
import com.wsl.HealthChallenge.utils.DataStorageUtils;
import com.wsl.HealthChallenge.utils.PMF;
import com.wsl.HealthChallenge.utils.Utils;

@Controller
public class HomePageController {
    @RequestMapping("/")
    public ModelAndView handleRequest(
            @RequestParam(value="name", defaultValue="") String challengeName,
            @RequestParam(value="id", defaultValue="") String challengeId,
            @RequestParam(value="contestType", defaultValue="") String contestTypeString,
            @RequestParam(value="idtaken", defaultValue="") String takenChallengeId,
            @RequestParam(value="idInvalid", defaultValue="") String invalidChallengeId,
            HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        ModelMap model = new ModelMap();
        model.addAttribute("challengeName", challengeName);
        model.addAttribute("challengeId", challengeId);
        if (!takenChallengeId.isEmpty()) {
            model.addAttribute("takenChallengeId", takenChallengeId);
        } else if (!invalidChallengeId.isEmpty()) {
            model.addAttribute("invalidChallengeId", invalidChallengeId);
        }  

        UserService userService = UserServiceFactory.getUserService();
        User user = userService.getCurrentUser();

        if (user != null) {
            model.addAttribute("signedInUserEmail", user.getEmail());
            model.addAttribute("signOutUrl", userService.createLogoutURL(request.getRequestURI()));
        } else {
            model.addAttribute("signInUrl", userService.createLoginURL(request.getRequestURI()));
        }

        // If the required fields haven't been filled out, show the create challenge form. 
        if (challengeId == null || challengeId.isEmpty() ||
                challengeName == null || challengeName.isEmpty()) {
            return new ModelAndView("create_challenge_view", model);
        }

        String encodedChallengeId = URLEncoder.encode(challengeId);
        if (!encodedChallengeId.equals(challengeId)) {
            StringBuilder builder = new StringBuilder();
            builder.append("?name=");
            builder.append(challengeName);
            builder.append("&idInvalid=");
            builder.append(challengeId);
            response.sendRedirect(builder.toString());
            return null;
        }

        // If not logged in, do that first and come back to the same URL.
        if (!Utils.ensureUserLoggedIn(request, response)) {
            return null;
        }

        ContestEntry challenge = DataStorageUtils.getContest(challengeId);
        if (challenge == null) {
            // Add the new challenge to the data store.
            Calendar calendar = Calendar.getInstance();
            Date startDate = calendar.getTime();

            // Default end date is set to 4 weeks later.
            calendar.add(Calendar.WEEK_OF_YEAR, 4);
            Date endDate = calendar.getTime();

            ContestType contestType = ContestType.getFromStringRepresentation(contestTypeString);
            challenge = new ContestEntry(challengeId, challengeName, contestType,
                    startDate, endDate, user.getUserId());

            DataStorageUtils.insertOrUpdateContest(challenge);

            // Insert or update the user.
            UserEntry userEntry = DataStorageUtils.getUserEntry(user.getUserId());
            boolean newUser = (userEntry == null);
            if (newUser) {
                userEntry = new UserEntry(user.getUserId(), 
                        request.getUserPrincipal().getName(),
                        user.getEmail(), null);
            } 
            userEntry.getAdminContests().add(challengeId);
            if (newUser) {
                JDOHelper.makeDirty(userEntry, "adminContests"); 
            }
            DataStorageUtils.insertOrUpdateUser(userEntry);

            // Forward to the admin page for the challenge.
            response.sendRedirect("/" + challenge.getId() + "/admin?created=true");
        } else {
            // A challenge with this ID already exists.
            // For now forward to the admin page.
            //response.sendRedirect(Utils.getFullUrl(request) + "&idtaken=1");
            StringBuilder builder = new StringBuilder();
            builder.append("?name=");
            builder.append(challengeName);
            builder.append("&idtaken=");
            builder.append(challengeId);
            response.sendRedirect(builder.toString());
            //response.sendRedirect("/" + challenge.getId() + "/idtaken");
        }
        PersistenceManager pm = PMF.get().getPersistenceManager();
        pm.close();
        return null;
    }
}